<?php

namespace Base;

use W3\Widget;
use W3\Util;
use W3\Json;
use W3\Plugin;
use W3\Timer;
use W3\Router;
use W3\Db\Query;
use function action_exists;
use function do_action;

/**
 * 内容基类
 *
 * @author edikud
 * @date 2022/10/22
 * @copyright Copyright (c) 2022 W3 (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */

class Contents extends Widget
{
    /**
     * 获取查询对象
     *
     * @return Query
     * @throws Exception
     */
    public function select(...$args): Query
    {
		return do_action( 
		    $this->parameter->main . '.select',
			$this,
			false,
			$this->db->select(...$args)->from('table.contents')
		);
    }
	
    /**
     * 取出mid
     *
     * @access protected
     * @return integer
     */
    protected function ___mid(): int
    {
		$mids = explode(',', $this->mids);
        return $mids[0];
    }

    /**
     * 将tags取出
     *
     * @access protected
     * @return array
     */
    protected function ___tags(): array
    {
	    $taglist = $this->have() ? Json::decode($this->tagsJson ?: '[]' ) : '';
	    $tags = [];

	    if($taglist) {
		    foreach($taglist as $tagID => $tag)
			{
			    $tags[$tagID] = [
				    'name'=>$tag['name'],
					'permalink'=> Router::buildUrl('tag', ['alias' => $tag['alias'], 'mid' => $tagID])
				];
		    }
	    }
        return $tags;
    }

    /**
     * 文章作者
     *
     * @access protected
     * @return Container
     */
    protected function ___author(): Widget
    {
        return $this->widget('User\Rows@' . $this->uid, 
		    ['uid' => $this->uid, 'limit' => 1]);
    }

    /**
     * 获取词义化日期
     *
     * @access protected
     * @return string
     */
    protected function ___dateWord(): string
    {
        return $this->date->word();
    }

    /**
     * 对文章的简短纯文本描述
     *
     * @access protected
     * @return string
     */
    protected function ___description(): ?string
    {
        $plainTxt = str_replace("\n", '', trim(strip_tags($this->intro)));
        $plainTxt = $plainTxt ? $plainTxt : $this->title;
        return Util::substr($plainTxt, 0, 100, '...');
    }

    /**
     * 获取文章内容
     *
     * @access protected
     * @return string
     */
    protected function ___content(): ?string
    {
		/** 插件接口 */
		return do_action('contents_text', $this, false, $this->text);
    }

    /**
     * 锚点id
     *
     * @access protected
     * @return string
     */
    protected function ___theId(): string
    {
        return $this->type . '-' . $this->cid;
    }
    
    /**
     * 回复框id
     * 
     * @access protected
     * @return string
     */
    protected function ___respondId(): string
    {
        return 'respond-' . $this->theId;
    }
    
    /**
     * 评论地址
     * 
     * @access protected
     * @return string
     */
    protected function ___commentUrl(): string
    {
        /** 生成反馈地址 */
        /** 评论 */
        return Router::buildUrl('feedback', ['permalink' => $this->pathinfo]);
    }
    
    /**
     * 回复地址
     * 
     * @access protected
     * @return string
     */
    protected function ___responseUrl(): string
    {
        return $this->permalink . '#' . $this->respondId;
    }

    /**
     * 通用过滤器
     *
     * @access public
     * @param array $value 需要过滤的行数据
     * @return array
     */
    public function filter(array $value): array
    {
		if (isset($value['created'])) {
			
            $value['date'] = Timer::make($value['created']);

            /** 生成日期 */
            $value['year'] = $value['date']->year;
            $value['month'] = $value['date']->month;
            $value['day'] = $value['date']->day;
		}

		if (isset($value['cid'], $value['type'], $value['alias'], $value['mids'])) {		
		
            $value['category'] = NULL;
            $value['directory'] = [];
            if (!empty($value['mids'])) {
			    /** 取出第一个分类作为alias条件 */
			    $mids = explode(',', $value['mids']);
                $value['directory'] = $this->widget('Category\Rows')->getParentsAlias($mids[0]);
			    $value['category'] = end($value['directory']);
            }

            $tmpAlias = $value['alias'];
            $tmpCategory = $value['category'];
            $tmpDirectory = $value['directory'];
            $value['alias'] = urlencode($value['alias']);
            $value['category'] = urlencode($value['category']);
            $value['directory'] = implode('/', array_map('urlencode', $value['directory']));

            /** 生成静态路径 */
            $value['pathinfo'] = Router::ruleUrl($value['type'], $value);

            /** 生成静态链接 */
            $value['permalink'] = Router::buildUrl($value['type'], $value);

            $value['alias'] = $tmpAlias;
            $value['category'] = $tmpCategory;
            $value['directory'] = $tmpDirectory;
		}
		
		/** 插件接口 */
		$value = do_action('contents_filter', $this, false, $value);
		
        return $value;
    }

    /**
     * 获取当前所有自定义模板
     *
     * @access public
     * @return array
     */
    public function getTemplates(): array
    {
        $files = glob($this->themeFile($this->config->theme, '*.php'));
        $result = [];

        foreach ($files as $file) {
            $info = Plugin::getInfo($file);
            $file = basename($file);

            if ('index.php' != $file && 'custom' == $info['title']) {
                $result[$file] = $info['description'];
            }
        }

        return $result;
    }

    /**
     * 将每行的值压入堆栈
     *
     * @access public
     * @param array $value 每行的值
     * @return array
     */
    public function push(array $value): array
    {
        $value = $this->filter($value);
        return parent::push($value);
    }

    /**
     * 输出文章发布日期
     *
     * @access public
     * @param string $format 日期格式
     */
    public function date(?string $format = NULL)
    {
        echo $this->date->format(empty($format) ? $this->config->postDateFormat : $format);
    }

    /**
     * 输出文章内容
     *
     * @access public
     * @param mixed $more 文章截取后缀
     */
    public function content($more = false)
    {
        echo false !== $more && !empty($this->excerpt)
		    ? $this->excerpt . "<p class=\"more\"><a href=\"{$this->permalink}\" title=\"{$this->title}\">{$more}</a></p>"
			: $this->content;
    }

    /**
     * 输出文章摘要
     *
     * @access public
     * @param integer $length 摘要截取长度
     * @param string $trim 摘要后缀
     */
    public function excerpt(int $length = 100, string $trim = '...')
    {
        echo Util::substr($this->intro, 0, $length, $trim);
    }

    /**
     * 输出标题
     *
     * @access public
     * @param integer $length 标题截取长度
     * @param string $trim 截取后缀
     */
    public function title(int $length = 0, string $trim = '...')
    {
        if (!action_exists('contents_title')) {
            echo $length > 0 ? Util::substr($this->title, 0, $length, $trim) : $this->title;
        } else {
			
			/** 插件接口 */
            echo do_action('contents_title', $this, false, $this->title, $length, $trim);
        }
    }

    /**
     * 输出文章评论数
     *
     * @access public
     */
    public function commentsNum(...$args)
    {
        if (empty($args)) {
            $args[] = '%d';
        }

        $num = intval($this->commentsNum);

        echo sprintf($args[$num] ?? array_pop($args), $num);
    }

	
    /**
     * 获取文章相应的操作权限
     *
     * @access public
     */
    public function allow(string $permission): bool
    {
        $allow = true;
        if ('edit' == $permission) {
            $allow = $this->have() && ($this->auth->check('editor', true) || $this->uid == $this->auth->uid);
        } else {
			
			if(!$this->auth->hasLogin()){
				return false;
			}

            /** 对自动关闭反馈功能的支持 */
            if ('comment' == $permission
			    && $this->config->commentsPostTimeout > 0
				&& $this->config->commentsAutoClose) {
					
                if ($this->config->time - $this->created > $this->config->commentsPostTimeout) {
                    return false;
                }
            }
			
			$permission = 'allow' . ucfirst($permission);
            $allow = $this->{$permission} == 1;
        }		
        return $allow;
    }

    /**
     * 输出文章分类
     *
     * @access public
     * @param string $split 多个分类之间分隔符
     * @param boolean $link 是否输出链接
     * @param string $default 如果没有则输出
     * @return void
     */
    public function category(string $split = ',', bool $link = true, ?string $default = NULL)
    {
	    $widgetMetas = $this->widget('Category\Rows');
	    $mids = explode(',', $this->mids);
        $result = [];
        foreach ($mids as $mid) 
		{
			$category = $widgetMetas->getCategory($mid);
            $result[] = $link ? '<a href="' . $category['permalink'] . '">' . $category['name'] . '</a>' : $category['name'];
        }

        if ($result) {
			echo implode($split, $result);
        } else {
            echo $default;
        }
    }

    /**
     * 输出文章标签
     *
     * @access public
     * @param string $split 多个标签之间分隔符
     * @param boolean $link 是否输出链接
     * @param string $default 如果没有则输出
     * @return void
     */
    public function tags(string $split = ',', bool $link = true, ?string $default = NULL)
    {
        /** 取出tags */
        if ($tags = $this->tags) {
            $result = [];
            foreach ($tags as $tag) 
			{
                $result[] = $link
				    ? '<a href="' . $tag['permalink'] . '">' . $tag['name'] . '</a>'
					: $tag['name'];
            }

            echo implode($split, $result);
        } else {
            echo $default;
        }
    }

    /**
     * 输出当前作者
     *
     * @access public
     * @param string $item 需要输出的项目
     * @return void
     */
    public function author(string $item = 'nickName')
    {
		if ($this->have()) {
            echo $this->author->{$item};
		}
    }
	
    protected function ___icon(): string
    {
		$icon = $this->pic;
		if($icon){
		    strpos($icon, '://') === FALSE && $icon = $this->cdnUrl($icon, false);
		}else{
			$icon = $this->config->staticUrl('images/no-image.png', false);
		}
        return $icon;
    }

	// 自动生成摘要
	public function autoIntro(?string $intro, ?string $content): ?string 
	{
		if(empty($intro)) {
			$intro = preg_replace('/\s{2,}/', ' ', strip_tags($content));
			if(false !== strpos($intro, '<!--more-->')){
			    list($intro) = explode('<!--more-->', $intro);
			}else{
				$intro = trim(Util::substr($intro, 0, 255, ''));
			}
		}else{
			$intro = str_replace(["\r\n", "\r", "\n"], '<br />', strip_tags($intro));
		}
		return $intro;
	}
}

